package com.hollysys.usersync.service.impl;

import com.hollysys.usersync.entity.Response;
import com.hollysys.usersync.entity.SyncResult;
import com.hollysys.usersync.entity.platform.Organization;
import com.hollysys.usersync.feign.OrgServiceInvoker;
import com.hollysys.usersync.interceptor.AppToken;
import com.hollysys.usersync.service.SyncOrgService;
import com.hollysys.usersync.utils.ExecuteUtil;
import lombok.extern.log4j.Log4j2;
import org.apache.commons.lang3.concurrent.BasicThreadFactory;
import org.springframework.lang.Nullable;
import org.springframework.stereotype.Service;
import org.springframework.util.ObjectUtils;

import javax.annotation.Resource;
import javax.validation.constraints.NotNull;
import java.util.*;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.ScheduledThreadPoolExecutor;
import java.util.function.Function;
import java.util.function.Predicate;
import java.util.stream.Collectors;

/**
 * 用户信息同步服务 - 实现类
 *
 * @author Jeremy Yim
 */
@Service
@Log4j2
public class SyncOrgServiceImpl implements SyncOrgService {

    @Resource
    private OrgServiceInvoker orgService;

    /**
     * 线程池
     */
    private final ExecutorService executorService = new ScheduledThreadPoolExecutor(10,
            new BasicThreadFactory.Builder().namingPattern("sync-schedule-pool-%d").daemon(true).build());

    /**
     * 获得组织信息字典
     *
     * @param key    字典键
     * @param value  字典值
     * @param filter 过滤条件
     * @return 组织信息字典
     */
    @Override
    public <R, V> Map<R, V> getOrgMap(@NotNull Function<Organization, R> key, @NotNull Function<Organization, V> value,
                                      @Nullable Predicate<Organization> filter) {
        // 获取组织全量列表
        Response<List<Organization>> orgListResponse = orgService.getOrgList(AppToken.getToken());
        if (orgListResponse.getStatus() != 0) {
            log.error("组织列表查询失败" + orgListResponse.getMessage());
            return new HashMap<>(0);
        }
        // 筛选分类
        filter = Objects.isNull(filter) ? u -> true : filter;
        return orgListResponse.getData().parallelStream()
                .filter(filter)
                .collect(Collectors.toMap(key, value));
    }


    /**
     * 新增组织
     *
     * @param orgList 组织实体列表
     * @return 操作结果
     */
    @Override
    public List<SyncResult> addOrganization(List<Organization> orgList) {
        // 新增组织
        List<ExecuteUtil.AsyncResult<Organization, Response<String>>> resultList = ExecuteUtil.batchAsyncCall(orgList, executorService,
                (org) -> orgService.addOrg(org, AppToken.getToken()));

        return resultList.stream().map(result -> SyncResult.builder()
                .status(result.getResult() && result.getValue().getStatus() == 0)
                .code(result.getRawParam().getCode())
                .message(result.getResult() ? result.getValue().getMessage() : result.getExceptionMessage())
                .build()
        ).collect(Collectors.toList());
    }

    /**
     * 修改组织信息
     *
     * @param orgList 组织机构实体列表
     * @return 成功修改的条数
     */
    @Override
    public List<SyncResult> updateOrganization(List<Organization> orgList) {
        // 更新组织
        List<ExecuteUtil.AsyncResult<Organization, Response<String>>> resultList = ExecuteUtil.batchAsyncCall(orgList, executorService,
                (org) -> orgService.updateOrg(org, AppToken.getToken()));

        return resultList.stream().map(result -> SyncResult.builder()
                .status(result.getResult() && result.getValue().getStatus() == 0)
                .code(result.getRawParam().getCode())
                .message(result.getResult() ? result.getValue().getMessage() : result.getExceptionMessage())
                .build()
        ).collect(Collectors.toList());
    }

    /**
     * 删除指定组织信息
     *
     * @param orgList 组织机构实体列表
     * @return 操作结果
     */
    @Override
    public List<SyncResult> deleteOrganization(List<Organization> orgList) {

        List<String> orgCodes = orgList.stream().map(Organization::getCode).collect(Collectors.toList());
        Map<String, String> orgMap = this.getOrgMap(Organization::getId, Organization::getCode, org -> orgCodes.contains(org.getCode()));

        List<ExecuteUtil.AsyncResult<String, Response<String>>> resultList = ExecuteUtil.batchAsyncCall(
                new ArrayList<>(orgMap.keySet()), executorService,
                (orgId) -> orgService.deleteOrg(orgId, AppToken.getToken()));

        return resultList.stream().map(result -> SyncResult.builder()
                .status(result.getResult() && result.getValue().getStatus() == 0)
                .code(orgMap.get(result.getRawParam()))
                .message(result.getResult() ? result.getValue().getMessage() : result.getExceptionMessage())
                .build()
        ).collect(Collectors.toList());

    }

    /**
     * 将组织code转换为id
     *
     * @param codeList 组织code列表
     * @return 组织code - ID列表
     */
    @Override
    public Map<String, String> convertOrgCode2Id(List<String> codeList) {
        if (ObjectUtils.isEmpty(codeList)) {
            return new HashMap<>(0);
        }
        // 获取组织全量列表
        Response<List<Organization>> orgListResponse = orgService.getOrgList(AppToken.getToken());
        if (orgListResponse.getStatus() != 0) {
            log.error("组织列表查询失败" + orgListResponse.getMessage());
            return new HashMap<>(0);
        }
        return orgListResponse.getData().parallelStream()
                .filter(org -> codeList.contains(org.getCode()))
                .collect(Collectors.toMap(Organization::getCode, Organization::getId));
    }

}
